﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommunityServer.Controls;
using CSLive.LiveMaps;
using Control=CSLive.ControlPanel.Editor.Control;
using Jayrock.Json;
using CommunityServer.Components;

[assembly: WebResource("CSLive.Resources.MapScript.js", "application/x-javascript")]
namespace CSLive.Controls
{
    public class Map : WrappedContentBase, ICSLiveControl
    {
        #region ICSLiveControl Members

        public Dictionary< string, Control > EditorControls
        {
            get
            {
                return new Dictionary<string, Control>();
            }
        }

        public string Name
        {
            get { return "Map"; }
        }

        public Uri DocsUri
        {
            get { return new Uri( "http://communityserverlive.com/controls/map/default.aspx" ); }
        }

        public string Description
        {
            get { return "Displays a Live Map"; }
        }

        public string Group
        {
            get { return "Live Maps"; }
        }

        #endregion

        #region Properties

        [Bindable( true )]
        [DefaultValue( "200px" )]
        [Localizable( true )]
        public Unit Width
        {
            get { return ( ViewState[ "Width" ] == null ) ? Unit.Parse( "200px" ) : ( Unit ) ViewState[ "Width" ]; }
            set { ViewState[ "Width" ] = value; }
        }

        [Bindable( true )]
        [DefaultValue( "200px" )]
        [Localizable( true )]
        public Unit Height
        {
            get { return ( ViewState[ "Height" ] == null ) ? Unit.Parse( "200px" ) : ( Unit ) ViewState[ "Height" ]; }
            set { ViewState[ "Height" ] = value; }
        }

        [Bindable(true)]
        [DefaultValue("")]
        [Localizable(true)]
        public string Style
        {
            get { return (ViewState["Style"] == null) ? "" : (string)ViewState["Style"]; }
            set { ViewState["Style"] = value; }
        }

        [Bindable(true)]
        [DefaultValue("")]
        [Localizable(true)]
        public string MapCssClass
        {
            get { return (ViewState["Css"] == null) ? "" : (string)ViewState["Css"]; }
            set { ViewState["Css"] = value; }
        }

        [Bindable( true )]
        [DefaultValue( "MapPaths" )]
        [Localizable( true )]
        public Use Use
        {
            get { return ( ViewState[ "Use" ] == null ) ? Use.MapPaths : ( Use ) ViewState[ "Use" ]; }
            set { ViewState[ "Use" ] = value; }
        }

        [Bindable(true)]
        [DefaultValue("Normal")]
        [Localizable(true)]
        public DashboardSize DashboardSize
        {
            get { return (ViewState["DashboardSize"] == null) ? DashboardSize.Normal : (DashboardSize)ViewState["DashboardSize"]; }
            set { ViewState["DashboardSize"] = value; }
        }

        [Bindable(true)]
        [DefaultValue("Hybrid")]
        [Localizable(true)]
        public MapStyle MapStyle
        {
            get { return (ViewState["MapStyle"] == null) ? MapStyle.Hybrid : (MapStyle)ViewState["MapStyle"]; }
            set { ViewState["MapStyle"] = value; }
        }


        #endregion

        #region Templates

        [Browsable( false )]
        [DefaultValue( null )]
        [PersistenceMode( PersistenceMode.InnerProperty )]
        public virtual MapPointCollection MapPoints
        {
            get { return ( ViewState[ "MapPoints" ] == null ) ? new MapPointCollection() : ( MapPointCollection ) ViewState[ "MapPoints" ]; }
            set { ViewState[ "MapPoints" ] = value; }
        }

        [Browsable( false )]
        [DefaultValue( null )]
        [PersistenceMode( PersistenceMode.InnerProperty )]
        public virtual MapPathCollection MapPaths
        {
            get { return ( ViewState[ "MapPaths" ] == null ) ? new MapPathCollection() : ( MapPathCollection ) ViewState[ "MapPaths" ]; }
            set { ViewState[ "MapPaths" ] = value; }
        }

        [Browsable( false )]
        [DefaultValue( null )]
        [PersistenceMode( PersistenceMode.InnerProperty )]
        public virtual LiveCollectionCollection Collections
        {
            get { return ( ViewState[ "Collections" ] == null ) ? new LiveCollectionCollection() : ( LiveCollectionCollection ) ViewState[ "Collections" ]; }
            set { ViewState[ "Collections" ] = value; }
        }

        #endregion

        protected override void BindDefaultContent( System.Web.UI.Control control, IDataItemContainer dataItemContainer )
        {
        }

        private object ds;
        public override object DataSource
        {
            get { return ds; }
            set { ds = value; }
        }

        protected override void OnLoad(EventArgs e)
        {
            if (!Page.ClientScript.IsClientScriptIncludeRegistered("livemapcontroljs"))
                Page.ClientScript.RegisterClientScriptInclude("livemapcontroljs", "http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1");
            Page.ClientScript.RegisterClientScriptResource(this.GetType(), "CSLive.Resources.MapScript.js");
        }

        protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteBeginTag("div");
            writer.WriteAttribute("id", this.ClientID);
            writer.WriteAttribute("style", string.Format("position: relative; Width: {0}; Height: {1}; {2}", Width, Height, Style));
            if (!string.IsNullOrEmpty(MapCssClass)) writer.WriteAttribute("class", MapCssClass);
            writer.Write(">");
            writer.WriteEndTag("div");
            writer.WriteLine("");
            writer.WriteBeginTag("script");
            writer.WriteAttribute("type", "text/javascript");
            string json = getJson();
            bool fix = false;
            if (Use == Use.UserLocation) json = getUserJson();
            writer.WriteLine(">");
            writer.WriteLine(string.Format("var {0}_map = new cslivemap('{0}', {1});", this.ClientID, json));
            writer.WriteLine("addLoadEvent(function() { ");
            writer.Indent++;
            writer.WriteLine(this.ClientID + "_map.map = new VEMap('" + this.ClientID + "'); ");
            writer.WriteLine(this.ClientID + "_map.map.SetDashboardSize(VEDashboardSize." + this.DashboardSize + ");");
            writer.WriteLine(this.ClientID + "_map.map.onLoadMap = function() { setTimeout(\"" + this.ClientID + "_map.Loaded();\", 1000) };  ");
            writer.WriteLine(this.ClientID + "_map.map.LoadMap(null, 16, VEMapStyle." + this.MapStyle + ", " + fix.ToString().ToLower() + ");");
            writer.Indent--;
            writer.WriteLine("});");
            writer.WriteLine("addUnLoadEvent(function() { " + this.ClientID + "_map.map.Dispose(); })");
            writer.WriteEndTag("script");
        }

        string getUserJson()
        {
            JsonTextWriter json = new JsonTextWriter();
            json.PrettyPrint = true;
            json.WriteStartObject();
            json.WriteMember("mapdata");
            json.WriteStartArray();
            json.WriteStartObject();
            json.WriteMember("mode");
            json.WriteString("points");
            json.WriteMember("points");
            json.WriteStartArray();
            json.WriteStartObject();
            json.WriteMember("mode");
            json.WriteString("search");
            json.WriteMember("searchfor");
            User user = null;
            if (ds != null) { if (ds is User) user = ds as User; else if (ds is Post) user = ((Post)ds).User; }
            if (user == null) user = CSControlUtility.Instance().GetCurrentUser(this);
            if (user == null) user = CSControlUtility.Instance().GetCurrentBoundObject<User>(this);
            if (user == null) user = CSContext.Current.User;

            json.WriteString(user.Profile.Location);
            json.WriteMember("Title");
            json.WriteString(string.Format("{0}'s Location", user.DisplayName));
            json.WriteMember("Description");
            json.WriteString(string.Format("{0} is located {1}", user.DisplayName, user.Profile.Location));
            json.WriteEndObject();
            json.WriteEndArray();
            json.WriteEndObject();
            json.WriteEndArray();
            json.WriteEndObject();
            json.Flush();
            json.Close();
            return json.ToString();
        }

        string getJson()
        {
            JsonTextWriter json = new JsonTextWriter();
            json.PrettyPrint = false;
            json.WriteStartArray();
            if (MapPoints.Count > 0)
            {
                json.WriteStartObject();
                json.WriteMember("mode");
                json.WriteString("points");
                json.WriteMember("points");
                json.WriteStartArray();
                foreach (MapPoint point in MapPoints)
                {
                    json.WriteStartObject();
                    json.WriteMember("mode");
                    if (!string.IsNullOrEmpty(point.SearchFor))
                    {
                        json.WriteString("search");
                        json.WriteMember("searchfor");
                        json.WriteString(point.SearchFor);
                    }
                    else
                    {
                        json.WriteString("latlong");
                        json.WriteMember("Lat");
                        json.WriteNumber(point.Lat);
                        json.WriteMember("Long");
                        json.WriteNumber(point.Long);
                    }
                    json.WriteMember("Title");
                    json.WriteString(point.Title);
                    json.WriteMember("Description");
                    json.WriteString(point.Description);
                    json.WriteEndObject();
                }
                json.WriteEndArray();
                json.WriteEndObject();
            }
            if (MapPaths.Count > 0)
            {
                json.WriteStartObject();
                json.WriteMember("mode");
                json.WriteString("paths");
                json.WriteMember("paths");
                json.WriteStartArray();
                foreach (MapPath path in MapPaths)
                {
                    json.WriteStartObject();
                    json.WriteMember("mode");
                    if (path.Fill != null) { json.WriteString("gon"); json.WriteMember("Fill"); json.WriteString(path.Fill.ToString()); }
                    else json.WriteString("line");
                    json.WriteMember("Stroke"); 
                    json.WriteString(path.Stroke.ToString());
                    json.WriteMember("Title");
                    json.WriteString(path.Title);
                    json.WriteMember("Description");
                    json.WriteString(path.Description);
                    json.WriteStartArray();
                    foreach (MapPoint point in path.MapPoints)
                    {
                        json.WriteStartObject();
                        json.WriteString("latlong");
                        json.WriteMember("Lat");
                        json.WriteNumber(point.Lat);
                        json.WriteMember("Long");
                        json.WriteNumber(point.Long);
                        json.WriteEndObject();
                    }
                    json.WriteEndArray();
                    json.WriteEndObject();
                }
                json.WriteEndArray();
                json.WriteEndObject();
            }
            if (Collections.Count > 0)
            {
                json.WriteStartObject();
                json.WriteMember("mode");
                json.WriteString("collections");
                json.WriteMember("collections");
                json.WriteStartArray();
                foreach (LiveCollection point in Collections)
                {
                    json.WriteStartObject();
                    json.WriteMember("mode");
                    if (!string.IsNullOrEmpty(point.Collection))
                    {
                        json.WriteString("collection");
                        json.WriteMember("Collection");
                        json.WriteString(point.Collection);
                    }
                    else
                    {
                        json.WriteString("georss");
                        json.WriteMember("GeoRss");
                        json.WriteString(point.GeoRss);
                    }
                    json.WriteEndObject();
                }
                json.WriteEndArray();
                json.WriteEndObject();
            }
            json.WriteEndArray();
            json.Flush();
            json.Close();
            return json.ToString();
        }
    }
}